using System;
using System.Globalization;
using System.Xml;
using DesignByContract;
using Outcoding.GraphGenerator.Entities;
using Outcoding.GraphGenerator.Util.Logging;

namespace Outcoding.GraphGenerator.Composition{
    public class MinValueBuilder : BuilderBase{
        #region Attributes

        private string enableAttr = "enabled";

        #endregion

        private readonly string mNodeName = XmlTagNames.minvalue.ToString();

        private XmlNode mNode;

        private string mNodePath{
            get { return "./" + mNodeName; }
        }

        public override void SelectNode(XmlDocument document){
            throw new Exception("The method or operation is not implemented.");
        }

        public override void Compose(){
            throw new Exception("The method or operation is not implemented.");
        }

        public override void Compose(XmlNode node){
            mNode = node.SelectSingleNode(mNodePath);
            try{
                BuildObject(mNode);
            }
            catch (PreconditionException preExc){
                LogManager.Instance.LogWarning("MinValue entity could not be created; process aborted.", preExc);
            }
        }

        public override void AppendToParent(object parent){
            Check.Require(parent is ValueAxis, "Parent object not a valid argument");
            (parent as ValueAxis).Min = (MinValue) mProduct;
        }

        private void BuildObject(XmlNode iAxisValueXmlNode){
            XmlTagNames tag = TagSelector(iAxisValueXmlNode);
            IAxisValue value = null;
            switch (tag){
                case XmlTagNames.minvalue:
                    value = new MinValue();
                    break;
                case XmlTagNames.maxvalue:
                    value = new MaxValue();
                    break;
                case XmlTagNames.scale:
                    value = new Scale();
                    break;
                default:
                    break;
            }
            if (value != null){
                try{
                    if (iAxisValueXmlNode.Attributes[enableAttr] != null)
                        value.IsEnabled = ParseIsEnableAttribute(iAxisValueXmlNode);
                    value.Value = ParseValue(iAxisValueXmlNode);
                }
                catch (PreconditionException preExc){
                    //log error
                    value = null;
                    throw;
                }
            }

            mProduct = value;
        }

        private bool ParseIsEnableAttribute(XmlNode iAxisValueXmlNode){
            Check.Require(iAxisValueXmlNode.Attributes[enableAttr] != null, "enabled attribute not present");
            return Boolean.Parse(iAxisValueXmlNode.Attributes[enableAttr].Value);
        }

        private double ParseValue(XmlNode iAxisValueXmlNode){
            return Double.Parse(iAxisValueXmlNode.InnerText.Trim(), CultureInfo.InvariantCulture.NumberFormat);
        }

        private XmlTagNames TagSelector(XmlNode iAxisValueXmlNode){
            XmlTagNames tag = XmlTagNames.unknown;
            switch (iAxisValueXmlNode.Name){
                case "minvalue":
                    tag = XmlTagNames.minvalue;
                    break;
                case "maxvalue":
                    tag = XmlTagNames.maxvalue;
                    break;
                case "scale":
                    tag = XmlTagNames.scale;
                    break;
            }
            return tag;
        }
    }
}